package com;

/**
 * @Author: fei.wu
 * @Email: fei.wu@rograndec.com
 * @CreateDate: 2018/6/15
 * @Version: 1.0
 */
public abstract class Lazy <T>{

    volatile T instance = null;

    /** Remembers the result, if the operation completed unexceptionally. */
    protected abstract T compute();

    /** Returns the same value, computing as necessary */
    public final T get() {
        T result = instance;
        if (result == null) {
            synchronized (this) {
                result = instance;
                if (result == null) {
                    instance = result = tryCompute();
                }
            }
        }
        return result;
    }

    /**
     * This is called in a synchronized block when the value to memorize hasn't yet been computed.
     *
     * <p>Extracted only for LazyCloseable, hence package protection.
     */
    T tryCompute() {
        return compute();
    }
}
